Support --default(…) in --value(…) and --modifier(…) to support fallback values#19989
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
WalkthroughAdds tests in packages/tailwindcss/src/utilities.test.ts asserting compiled CSS is empty when `--value(...)` is omitted or unresolved, and that `--default(...)` nested inside `--value(...)` enables resolution (including inside `calc(...)` and alongside `--modifier(...)`). Parser normalization no longer appends a trailing `-*` when a functional `(` is present. Validation now treats a missing candidate `value` as eligible for `--default(...)` lookup and requires at least one resolvable `--value(...)` branch; modifier resolution remains separate. No public API changes. 🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Comment |
754bfc8 to
9dbd228
Compare
--default(…) option in --value(…) to support fallback values--default(…) in --value(…) and --modifier(…) to support fallback values
9dbd228 to
24b152e
Compare
Confidence Score: 5/5Safe to merge — no P0 or P1 issues found; implementation is correct and well-tested. The logic changes are internally consistent: the nullable-value short-circuit in resolveValueFunction, the updated --modifier guard (modifier !== null), the --default(…) function recognition in the storage arg-normalization pass, and the theme-key auto-suffix guard (!arg.includes('(')) all work together correctly. Five targeted tests cover the key combinations. No behavioral regressions on existing paths were found. No files require special attention. Reviews (3): Last reviewed commit: "remove unnecessary check" | Re-trigger Greptile |
…20005) While working on #19989, I noticed that `--value(…)` inside functional `@utility` definitions is not required right now. That means that the following CSS is valid: ```css @Utility foo-* { color: red; } ``` But this doesn't really makes sense, because this now accepts a value and `foo-a`, `foo-b` and `foo-c` would generate the following CSS: ```css .foo-a { color: red; } .foo-b { color: red; } .foo-c { color: red; } ``` The `a`, `b`, and `c` are not doing anything here apart from making your CSS bigger. So this is very likely an actual bug that you forgot to use `--value(…)`. Additionally, if a `--value(…)` was used, but it didn't resolve anything, then we already properly discared the candidate. ## Test plan 1. Add test to ensure `--value(…)` is required in functional `@utility` definitions 2. Existing tests pass
This allows us to re-implement functional utilities with a default value in CSS using `@utility`. Used the explicit `--default()` argument of `--value()` for a few reasons. 1. It's explicit about being a falllback value. If you have `@utility foo-*`, then you want to be able to use `foo`, but `foo-bad` should not compile. 2. When `--value(…)` is used in (complex) property values (think a bunch of `calc(…)` expressions), then we don't need a separate property for this. One of the ideas was to have a literal fallback: ```css @Utility tab-* { tab-size: 4; tab-size: --value(number); } ``` For `tab`, this would compile to: ```css .tab { tab-size: 4; } ``` For `tab-123`, this would compile to: ```css .tab { tab-size: 4; tab-size: 123; } ``` Getting rid of the `tab-size: 4` would be an option, but it's a common pattern in real CSS for fallback values (think hex background color, over a more modern `oklch` color). For `tab-foo`, this would compile to: ```css .tab { tab-size: 4; } ``` Which means that we have an infinite amount classes that would result in the same class, which is bad. We could special case this one because the internal `value` would still be `null`, but it might be too confusing. This syntax without the `--default` also means repetition of certain properties. Add `--modifier(…)` to the mix, and there is even more repetition going on. Another option to consider is that the default fallback is just another option in the `--value(…, 4)`, but if a default fallback is a keyword, then there is a chance that this might conflict with actual keywords we interpret.
24b152e to
d196a77
Compare
If we didn't resolve even if we have a modifier, then we _also_ should remove the declaration and stop immediately. So both branches are the same.
Direct link: https://tailwindcss-com-git-feat-document-default-fn-tailwindlabs.vercel.app/docs/adding-custom-styles#default-values This PR documents the `--default(…)` option that can be used in `--value(…)` and `--modifier(…)` when defining custom functional utilities in CSS using `@utility`. This was been implemented in tailwindlabs/tailwindcss#19989
This PR adds a new
--default(…)option that can be used inside--value(…)or--modifier(…)such that functional utilities without an explicit value/modifier can still be defined as a functional utility.For example, let's say you have a
tab-*utility:This allows us to use
tab-1,tab-2,tab-4and so on. But it also allows us to use justtab. In this case thetab-sizewould use a default value of4:Main motivation is to be able to re-implement utilities such as
shadow/50purely in CSS. It's also something we support in the JS based APIs, but not in the CSS based one, so while it's a "new" feature, it's more like a missing feature right now, and often a reason for people to use the JS based APIs instead.For consistency reasons, this is also implemented for
--modifier(…)such that you can use a default value there. E.g. when re-implementingtext-smwhere a defaultline-heightis set without the explicit use of a modifier.Other approaches I considered
Used the explicit
--default(…)argument of--value(…)for a few reasons.@utility foo-*, then you want to be able to usefoo, butfoo-badshould not compile.--value(…)is used in (complex) property values (think a bunch ofcalc(…)expressions), then we don't need a separate property for this.One of the ideas was to have a literal fallback:
For
tab, this would compile to:For
tab-123, this would compile to:Getting rid of the
tab-size: 4would be an option, but it's a common pattern in real CSS for fallback values (think hex background color, over a more modernoklchcolor).For
tab-foo, this would compile to:This syntax without the
--default(…)also means repetition of certain properties. Add--modifier(…)to the mix, and there is even more repetition going on.Another option to consider is that the default fallback is just another option in the
--value(…, 4), but if a default fallback is a keyword, then there is a chance that this might conflict with actual keywords we interpret.Fixes: #16824
Test plan